package tgc.edu.ljc.web.controller;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import tgc.edu.ljc.custom.AjaxResult;
import tgc.edu.ljc.custom.CommonController;
import tgc.edu.ljc.custom.NonStaticResourceHttpRequestHandler;
import tgc.edu.ljc.custom.TablePageable;
import tgc.edu.ljc.custom.TimeUtils;
import tgc.edu.ljc.entity.DataSum;
import tgc.edu.ljc.entity.SysDept;
import tgc.edu.ljc.entity.SysFile;
import tgc.edu.ljc.entity.SysRole;
import tgc.edu.ljc.entity.SysUser;
import tgc.edu.ljc.security.UserUtils;
import tgc.edu.ljc.service.DataSumService;
import tgc.edu.ljc.service.SysDeptService;
import tgc.edu.ljc.service.SysFileService;
import tgc.edu.ljc.service.SysUserService;
import tgc.edu.ljc.web.form.SysFileForm;

@Controller
@RequestMapping(value = "/sysFile")
public class SysFileController extends CommonController<SysFile, Integer, SysFileForm> {
	@Autowired
	private SysFileService fileService;
	@Autowired
	private DataSumService datasumService;
	@Autowired
	private SysUserService userService;
	@Autowired
	private UserUtils userUtils;
	@Autowired
	private SysDeptService deptService;
	@Value("${web.file-url}")
	public String url;
	@Autowired
	private  NonStaticResourceHttpRequestHandler  nonStaticResourceHttpRequestHandler;
	
	
	
	@Override
	public void manage(ModelMap map) {
		List<DataSum> fileNatures = datasumService.findFileNatures();
		List<DataSum> fileTypes = datasumService.findFileTypes();
		map.put("fileNatures", fileNatures);
		map.put("fileTypes",fileTypes);
		super.manage(map);
	}

	@Override
	public Object page(TablePageable pageParam, SysFileForm form) {
		PageRequest pageable = pageParam.bulidPageRequest();
		SysUser user = userUtils.getUser();
		// 查询当前用户查看权限
		boolean isAdmin = false;
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			//if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
			if ( r.getCode().equals("ROLE_MANAGER") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			//List<SysDept> list1 = new ArrayList<>();
			//List<SysDept> list = fileService.setSysDepts(user.getDept(),list1);
			//spec = buildSpec2(form, user).and(buildSpec4(list));
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageable);
		return AjaxResult.bulidPageResult(page);
	}

	@Override
	public Object delete(Integer id) {
		try {
			SysUser user = userUtils.getUser();
			boolean b = false;
			SysFile findById = fileService.findById(id);
			for (SysRole r : user.getRoles()) { // 判断当前用户是否具有管理员权限
				//if (r.getCode().equals("ROLE_ADMIN")) {
				if (r.getCode().equals("ROLE_MANAGER")) {
					b = true;
				}
			}
			if (!user.getUsername().equals(findById.getUploadsUsername()) && !b) {
				return new AjaxResult(false, "删除失败，您没有该权限！");
			} else {
				findById.setIsUsed(false);
				findById.setDelTime(TimeUtils.getStringDate());
				fileService.save(findById);
				return new AjaxResult("数据删除成功");
			}
		} catch (Exception e) {
		}
		return new AjaxResult("数据删除失败");
	}

	@Override
	public void edit(SysFileForm form, ModelMap map) throws InstantiationException, IllegalAccessException {
		List<DataSum> dataSums = datasumService.findAll();
		List<DataSum> fileType = null, fileNature = null;
		for (int i = 0; i < dataSums.size(); i++) {
			if (dataSums.get(i).getParentId() == null) {
				switch (dataSums.get(i).getCode()) {
				case "DICT_FILE_TYPE":
					fileType = dataSums.get(i).getChildren();
					break;
				case "DICT_FILE_DOCUMENTS":
					fileNature = dataSums.get(i).getChildren();
					break;
				default:
					break;
				}
			}
		}
		if (form.getId() != null) {
			boolean edit = true;
			map.put("edit", edit);
		}else {
			boolean edit = false;
			map.put("edit", edit);
		}
		map.put("fileType", fileType);
		map.put("fileNature", fileNature);
		super.edit(form, map);
	}

	@Override
	public Object save(SysFileForm form) {
		boolean savefile=true;
		List<String> filenames=new ArrayList<>();
		if (form.getId() == null) {
			for (MultipartFile file : form.getFile2()) {
				form.setFile(file);
				boolean savefile2 = fileService.savefile(form);
				if(!savefile2) {
					savefile=false;
					filenames.add(file.getOriginalFilename());
				}
			}
			if (savefile) {
				return new AjaxResult("文件上传成功");
			} else {
				return new AjaxResult(false,filenames.toString()+ "文件上传失败");
			}
		} else {
			SysUser user = userUtils.getUser();
			SysFile findById = fileService.findById(form.getId());
			Boolean hasRole = userUtils.hasRole("ROLE_MANAGER");
			if (!hasRole && !user.getUsername().equals(findById.getUploadsUsername())) {
				return new AjaxResult(false, "修改失败，您没有修改该文件的权限！");
			}
			fileService.mySave(findById, form);
			return new AjaxResult("保存成功");
		}
	}

	// 判断该文件是否损坏
	@RequestMapping(value = {"/download","/app/download"})
	@ResponseBody
	public Object download(String fileUuid, HttpServletRequest request, HttpServletResponse response) {
		boolean savefile = fileService.download(fileUuid, request, response);
		if (savefile) {
			return fileUuid;
		} else {
			return new AjaxResult(false, "下载失败！文件损坏或不存在！");
		}
	}

	@RequestMapping(value = "/download2")
	@ResponseBody
	public void download2(String fileUuid, HttpServletRequest request, HttpServletResponse response) {
		//response.addHeader("Access-Control-Allow-Origin", "*");
		fileService.download(fileUuid, request, response);
	}

	public Specification<SysFile> buildSpec1(SysFileForm form) {
		
		Specification<SysFile> spec = new Specification<SysFile>() {
			private static final long serialVersionUID = 8351493853179634432L;
			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules=new HashSet<>();
				rules.add(cb.equal(root.get("isUsed"), true));

				if(StringUtils.hasText(form.getUserDept())) { 
					Predicate userDept = cb.equal(root.get("userDept").get("id"),Integer.valueOf(form.getUserDept()));
					rules.add(userDept);
				}
				if(StringUtils.hasText(form.getFileTitle())) { 
					Predicate fileTitle = cb.like(root.get("fileTitle"),"%"+form.getFileTitle()+"%");
					rules.add(fileTitle);
				}
				if(form.getFileType()!=null) {
					rules.add(cb.equal(root.get("fileType").get("id"), form.getFileType()));
				}
				
				if(StringUtils.hasText(form.getFileName())) {
					Predicate name = cb.like(root.get("fileName"), "%"+form.getFileName()+"%");
					rules.add(name);
				}
				if(StringUtils.hasText(form.getFileUser())) {
					Predicate difficultylevel = cb.like(root.get("uploadsName"), "%"+form.getFileUser()+"%");
					rules.add(difficultylevel);
				}
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		if(StringUtils.hasText(form.getSearch())) {
			return spec.and(buildSpec7(form.getSearch()));
		}else {
			return spec;
		}
	}

	public Specification<SysFile> buildSpec2(SysFileForm form, SysUser user) {

		Specification<SysFile> spec = new Specification<SysFile>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				//rules.add(cb.equal(root.get("isUsed"), true));
				if(StringUtils.hasText(form.getUserDept())) { 
					Predicate userDept = cb.equal(root.get("userDept").get("id"),Integer.valueOf(form.getUserDept()));
					rules.add(userDept);
				}
				if(StringUtils.hasText(form.getFileTitle())) { 
					Predicate fileTitle = cb.like(root.get("fileTitle"),"%"+form.getFileTitle()+"%");
					rules.add(fileTitle);
				}
				if(StringUtils.hasText(form.getFileName())) {
					Predicate name = cb.like(root.get("fileName"), "%"+form.getFileName()+"%");
					rules.add(name);
				}
				if(StringUtils.hasText(form.getFileUser())) {
					Predicate difficultylevel = cb.like(root.get("uploadsUsername"), "%"+form.getFileUser()+"%");
					rules.add(difficultylevel);
				}
				if(form.getFileType()!=null) {
					rules.add(cb.equal(root.get("fileType").get("id"), form.getFileType()));
				}
				
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		Specification<SysFile> spec3 = buildSpec3();
		Specification<SysFile> spec5 = buildSpec5(user);
		if(StringUtils.hasText(form.getSearch())) {
			return spec.and(spec3).and(spec5).and(buildSpec7(form.getSearch()));
		}else {
			return spec.and(spec3).and(spec5);
		}
	}

	public Specification<SysFile> buildSpec3() {

		Specification<SysFile> spec = new Specification<SysFile>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				rules.add(cb.equal(root.get("isUsed"), true));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}
	public Specification<SysFile> buildSpec4(List<SysDept> list) {
		
		Specification<SysFile> spec = new Specification<SysFile>() {
			
			
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				for (SysDept sysDept : list) {
					rules.add(cb.equal(root.get("userDept").get("id"), sysDept.getId()));
				}
				return cb.or(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}
	
	public Specification<SysFile> buildSpec5(SysUser user) {
		
		Specification<SysFile> spec = new Specification<SysFile>() {
			
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules = new HashSet<>();
				System.out.println(root.get("uploadsUsername")+":"+user.getUsername());
				rules.add(cb.equal(root.get("uploadsUsername"), user.getUsername())); // 该用户自己上传的文件
				rules.add(cb.equal(root.get("fileNature").get("name"), "公共")); // 公共的文件
				return cb.or(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec.or(buildSpec6(user));
	}
	
	/***
	 * 用户部门共享的文件查询条件
	 * @param user 用户
	 * @return
	 */
	public Specification<SysFile> buildSpec6(SysUser user){
		Specification<SysFile> spec=new Specification<SysFile>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules=new HashSet<>();
				rules.add(cb.equal(root.get("fileNature").get("code"), "DICT_TOPANDSAME"));//部门共享
				Integer id = user.getId();
				List<Integer> ids = deptService.findAllChildrenId(id);
				rules.add(root.get("userDept").get("id").in(ids));
				return cb.and(rules.toArray(new Predicate[rules.size()]));
			}
			
		};
		
		return spec;
	}
	
	public Specification<SysFile> buildSpec7(String search){
		@SuppressWarnings("serial")
		Specification<SysFile> spec=new Specification<SysFile>() {

			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				HashSet<Predicate> rules=new HashSet<>();
				if(StringUtils.hasText(search)) {
					rules.add(cb.like(root.get("fileTitle"), "%"+search+"%"));
					rules.add(cb.like(root.get("fileName"), "%"+search+"%"));
					rules.add(cb.like(root.get("fileRemark"), "%"+search+"%"));
					rules.add(cb.like(root.get("updateTime"), "%"+search+"%"));
					rules.add(cb.like(root.get("uploadsName"), "%"+search+"%"));
				}
				return cb.or(rules.toArray(new Predicate[rules.size()]));
			}
		};
		return spec;
	}
	public Specification<SysFile> buildSpec8(String lastTime){
		Specification<SysFile> spec=new Specification<SysFile>() {
			@Override
			public Predicate toPredicate(Root<SysFile> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				return cb.lessThan(root.get("updateTime"),lastTime);
			}
		};
		return spec;
	}
	
	/***
	 * 图片缩略图列表
	 * @param modelMap
	 * @return
	 */
	@RequestMapping(value="/pictureList")
	public String pictureList(String search,ModelMap modelMap) {
		return "sysFile/pictureList";
	}
	
	/***
	 * 视频缩略图列表
	 * @param search
	 * @param modelMap
	 * @return
	 */
	@RequestMapping(value="/videoList")
	public String videoList(String search,ModelMap modelMap) {
		return "sysFile/videoList1";
	}
	/***
	 * 音频缩略图列表
	 * @param search 搜索字段内容
	 * @return
	 */
	@RequestMapping(value="/voiceList")
	public String voiceList(String search) {
		return "sysFile/voiceList";
	}
	/***
	 * office文件缩略图列表
	 * @param search 搜索字段内容
	 * @return
	 */
	@RequestMapping(value="/officeList")
	public String officeList(String search) {
		return "sysFile/officeList";
	}
	
	
	/****
	 * 下载缩略图
	 * @param fileUuid
	 * @param response
	 */
	@RequestMapping(value= {"/download3","/app/download3"})
	@ResponseBody
	@CrossOrigin
	public void download3(String fileUuid,HttpServletResponse response) {
		fileService.downloadShortImage(fileUuid, response);
	}
	
	@RequestMapping(value= {"/imagePage","/app/imagePage"})
	@ResponseBody
	@CrossOrigin
	public Object imagePage(Pageable pageRequest,String search,String userName,String lastTime) {
		SysFileForm form=new SysFileForm();
		form.setFileType(7);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user=null;
		if(StringUtils.hasText(userName)) {
			user=userService.findByUsername(userName);
		}else {
			user = userUtils.getUser();
		}
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			//if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
			if ( r.getCode().equals("ROLE_MANAGER") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		if(StringUtils.hasText(lastTime)) {
			spec=spec.and(buildSpec8(lastTime));
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}

	@RequestMapping(value= {"/videoPage","/app/videoPage"})
	@ResponseBody
	@CrossOrigin
	public Object videoPage(Pageable pageRequest,String search,HttpServletRequest request,String userName,String lastTime) throws IOException {
		SysFileForm form=new SysFileForm();
		form.setFileType(8);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user=null;
		if(StringUtils.hasText(userName)) {
			user=userService.findByUsername(userName);
		}else {
			user= userUtils.getUser();
		}
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			//if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
			if ( r.getCode().equals("ROLE_MANAGER") ) { // 当前用户是否为管理员
				isAdmin = true;
				break;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		if(StringUtils.hasText(lastTime)) {
			spec=spec.and(buildSpec8(lastTime));
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}
	
	@RequestMapping(value= {"/voicePage","/app/voicePage"})
	@ResponseBody
	@CrossOrigin
	public Object voicePage(Pageable pageRequest,String search,String userName) {
		SysFileForm form=new SysFileForm();
		form.setFileType(9);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user=null;
		if(StringUtils.hasText(userName)) {
			user=userService.findByUsername(userName);
		}else {
			user = userUtils.getUser();
		}
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			//if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
			if ( r.getCode().equals("ROLE_MANAGER") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}

	
	@RequestMapping(value= {"/officePage","/app/officePage"})
	@ResponseBody
	@CrossOrigin
	public Object officePage(Pageable pageRequest,String search,String userName) {
		SysFileForm form=new SysFileForm();
		form.setFileType(2);
		if(StringUtils.hasText(search)) {
			form.setSearch(search);
		}
		boolean isAdmin = false;
		SysUser user;
		if(StringUtils.hasText(userName)) {
			user=userService.findByUsername(userName);
		}else {
			user= userUtils.getUser();
		}
		List<SysRole> roles = user.getRoles();
		Specification<SysFile> spec = null;
		for (SysRole r : roles) {
			//if ( r.getCode().equals("ROLE_ADMIN") ) { // 当前用户是否为管理员
			if ( r.getCode().equals("ROLE_MANAGER") ) { // 当前用户是否为管理员
				isAdmin = true;
			}
		}
		if (isAdmin) {
			spec = buildSpec1(form);
		} else {
			spec = buildSpec2(form, user);
		}
		Page<SysFile> page = fileService.findAll(spec, pageRequest);
		return page;
	}
	
	@RequestMapping(value="/video")
	public @ResponseBody void video(String fileUuid, HttpServletResponse response)throws Exception{
		SysFile sysFile = fileService.findByFileUuid(fileUuid);
		File file=new File(url, sysFile.getFileUuid());
		if(!file.exists()) {
			System.out.println("文件不存在");
		}
		FileInputStream in = new FileInputStream(file);
		ServletOutputStream out = response.getOutputStream();
		byte[] b = null;
		while(in.available() >0) {
			if(in.available()>10240) {
				b = new byte[10240];
			}else {
				b = new byte[in.available()];
			}
			in.read(b, 0, b.length);
			out.write(b, 0, b.length);
		}
		in.close();
		out.flush();
		out.close();
	}
	
	@GetMapping(value="/video1")
	public StreamingResponseBody video1(String fileUuid) {
		return new StreamingResponseBody() {
			
			@Override
			public void writeTo(OutputStream outputStream) throws IOException {
				File inFile=new File(url, fileUuid);
				InputStream in=new FileInputStream(inFile);
				byte[] buf=new byte[2048];
				int size;
				while((size=in.read(buf))!=-1) {
					outputStream.write(buf, 0, size);
				}
				in.close();
			}
		};
	}
	
	@RequestMapping(value="/showVideo")
	public String showVideo(String fileUuid,ModelMap modelMap) {
		SysFile sysFile = fileService.findByFileUuid(fileUuid);
		modelMap.put("model", sysFile);
		return "sysFile/showVideo";
	}
	
	/*@RequestMapping(value="/videoPreview")
	
	public void videoPreview(HttpServletRequest request,HttpServletResponse response) throws Exception {
		//request.setCharacterEncoding("utf-8");
		String fileUuid = request.getParameter("fileUuid");
		//SysFile sysFile = fileService.findByFileUuid(fileUuid);
		File file=new File(url,fileUuid+".mp4");
		if(file.exists()) {
			String mimeType = Files.probeContentType(file.toPath());
			if(!StringUtils.isEmpty(mimeType)) {
				response.setContentType(mimeType);
				request.setAttribute(NonStaticResourceHttpRequestHandler.ATTR_FILE, file.toPath());
				nonStaticResourceHttpRequestHandler.handleRequest(request, response);
			}else {
	            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
	            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
	        }
		}
	}*/
	
	@RequestMapping(value="/videoPreview")
	@ResponseBody
	public FileSystemResource videoPreview(String fileUuid,HttpServletResponse response) throws IOException {
		File file=new File(url, fileUuid);
		if(file.exists()) {
			response.setContentType("video/mp4");
			return new FileSystemResource(file);
		}else {
			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
			response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
			return null;
		}
	}
	
	@RequestMapping(value="/getVideo2")
	@ResponseBody
	public void getPreview2(String fileUuid,HttpServletResponse response) {
		
		File file=new File(url,fileUuid);
		response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader("Content-Disposition", "attachment; filename="+file.getName().replace(" ", "_"));
        InputStream iStream;
		try {
			iStream = new FileInputStream(file);
			IOUtils.copy(iStream, response.getOutputStream());
			response.flushBuffer();
		} catch (FileNotFoundException e) {
			response.setStatus(HttpStatus.NOT_FOUND.value());
		} catch (IOException e) {
			response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
		}
	}
	
	@RequestMapping(value = "/getVedio")
    public void getVedio(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String filename = request.getParameter("fileUuid");

        //String path = "d:/tmp/pic/bb.mp4";
        BufferedInputStream bis = null;
        try {
            File file = new File(url,filename);
            if (file.exists()) {
                long p = 0L;
                long toLength = 0L;
                long contentLength = 3L;
                int rangeSwitch = 0; // 0,从头开始的全文下载；1,从某字节开始的下载（bytes=27000-）；2,从某字节开始到某字节结束的下载（bytes=27000-39000）
                long fileLength;
                String rangBytes = "";
                fileLength = file.length();

                // get file content
                InputStream ins = new FileInputStream(file);
                bis = new BufferedInputStream(ins);

                // tell the client to allow accept-ranges
                response.reset();
                response.setHeader("Accept-Ranges", "bytes");

                // client requests a file block download start byte
                String range = request.getHeader("Range");
                if (range != null && range.trim().length() > 0 && !"null".equals(range)) {
                    response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
                    rangBytes = range.replaceAll("bytes=", "");
                    if (rangBytes.endsWith("-")) {  // bytes=270000-
                        rangeSwitch = 1;
                        p = Long.parseLong(rangBytes.substring(0, rangBytes.indexOf("-")));
                        contentLength = fileLength - p;  // 客户端请求的是270000之后的字节（包括bytes下标索引为270000的字节）
                    } else { // bytes=270000-320000
                        rangeSwitch = 2;
                        String temp1 = rangBytes.substring(0, rangBytes.indexOf("-"));
                        String temp2 = rangBytes.substring(rangBytes.indexOf("-") + 1, rangBytes.length());
                        p = Long.parseLong(temp1);
                        toLength = Long.parseLong(temp2);
                        contentLength = toLength - p + 1; // 客户端请求的是 270000-320000 之间的字节
                    }
                } else {
                    contentLength = fileLength;
                }

                // 如果设设置了Content-Length，则客户端会自动进行多线程下载。如果不希望支持多线程，则不要设置这个参数。
                // Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节]
                response.setHeader("Content-Length", new Long(contentLength).toString());

                // 断点开始
                // 响应的格式是:
                // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
                if (rangeSwitch == 1) {
                    String contentRange = new StringBuffer("bytes ").append(new Long(p).toString()).append("-")
                            .append(new Long(fileLength - 1).toString()).append("/")
                            .append(new Long(fileLength).toString()).toString();
                    response.setHeader("Content-Range", contentRange);
                    bis.skip(p);
                } else if (rangeSwitch == 2) {
                    String contentRange = range.replace("=", " ") + "/" + new Long(fileLength).toString();
                    response.setHeader("Content-Range", contentRange);
                    bis.skip(p);
                } else {
                    String contentRange = new StringBuffer("bytes ").append("0-")
                            .append(fileLength - 1).append("/")
                            .append(fileLength).toString();
                    response.setHeader("Content-Range", contentRange);
                }

                String fileName = file.getName();
                response.setContentType("application/octet-stream");
                response.addHeader("Content-Disposition", "attachment;filename=" + fileName);

                OutputStream out = response.getOutputStream();
                int n = 0;
                long readLength = 0;
                int bsize = 1024;
                byte[] bytes = new byte[bsize];
                if (rangeSwitch == 2) {
                    // 针对 bytes=27000-39000 的请求，从27000开始写数据
                    while (readLength <= contentLength - bsize) {
                        n = bis.read(bytes);
                        readLength += n;
                        out.write(bytes, 0, n);
                    }
                    if (readLength <= contentLength) {
                        n = bis.read(bytes, 0, (int) (contentLength - readLength));
                        out.write(bytes, 0, n);
                    }
                } else {
                    while ((n = bis.read(bytes)) != -1) {
                        out.write(bytes, 0, n);
                    }
                }
                out.flush();
                out.close();
                bis.close();
            } else {
//                if (logger.isDebugEnabled()) {
//                    logger.debug("Error: file " + path + " not found.");
//                }
            }
        } catch (IOException ie) {
            // 忽略 ClientAbortException 之类的异常
        } catch (Exception e) {
//            logger.error(e.getMessage());
        }


    }
}
